#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include<ctype.h>
#include"fsdata.h"

#define BUFSIZE 1024
#define PROT_ARP 0x0806
#define PROT_IP  0x0800

#define ARP_HDR_SIZE	(8+20)		/* Size assuming ethernet	*/

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;

/* IPv4 addresses are always 32 bits in size 
struct in_addr {
	__be32 s_addr;
};
*/
struct ethernet_hdr {
	u8		et_dest[6];	/* Destination node		*/
	u8		et_src[6];	/* Source node			*/
	u16		et_protlen;	/* Protocol or length		*/
};
struct ip_hdr {
	u8		ip_hl_v;	/* header length and version	*/
	u8		ip_tos;		/* type of service		*/
	u16		ip_len;		/* total length			*/
	u16		ip_id;		/* identification		*/
	u16		ip_off;		/* fragment offset field	*/
	u8		ip_ttl;		/* time to live			*/
	u8		ip_p;		/* protocol			*/
	u16		ip_sum;		/* checksum			*/
	struct in_addr	ip_src;		/* Source IP address		*/
	struct in_addr	ip_dst;		/* Destination IP address	*/
};

/*
 *	Address Resolution Protocol (ARP) header.
 */
struct arp_hdr {
	u16		ar_hrd;		/* Format of hardware address	*/
#   define ARP_ETHER	    1		/* Ethernet  hardware address	*/
	u16		ar_pro;		/* Format of protocol address	*/
	u8		ar_hln;		/* Length of hardware address	*/
#   define ARP_HLEN	6
	u8		ar_pln;		/* Length of protocol address	*/
#   define ARP_PLEN	4
	u16		ar_op;		/* Operation			*/
#   define ARPOP_REQUEST    1		/* Request  to resolve  address	*/
#   define ARPOP_REPLY	    2		/* Response to previous request	*/

#   define RARPOP_REQUEST   3		/* Request  to resolve  address	*/
#   define RARPOP_REPLY	    4		/* Response to previous request */

	/*
	 * The remaining fields are variable in size, according to
	 * the sizes above, and are defined as appropriate for
	 * specific hardware/protocol combinations.
	 */
	u8		ar_data[0];
#define ar_sha		ar_data[0]
#define ar_spa		ar_data[ARP_HLEN]
#define ar_tha		ar_data[ARP_HLEN + ARP_PLEN]
#define ar_tpa		ar_data[ARP_HLEN + ARP_PLEN + ARP_HLEN]
#if 0
	u8		ar_sha[];	/* Sender hardware address	*/
	u8		ar_spa[];	/* Sender protocol address	*/
	u8		ar_tha[];	/* Target hardware address	*/
	u8		ar_tpa[];	/* Target protocol address	*/
#endif /* 0 */
};
/* Ethernet header size */
#define ETHER_HDR_SIZE	(sizeof(struct ethernet_hdr))

#define ISO_G        0x47
#define ISO_E        0x45
#define ISO_T        0x54
#define ISO_P        0x50
#define ISO_O        0x4f
#define ISO_S        0x53
#define ISO_T        0x54
#define ISO_slash    0x2f
#define ISO_c        0x63
#define ISO_g        0x67
#define ISO_i        0x69
#define ISO_space    0x20
#define ISO_nl       0x0a
#define ISO_cr       0x0d
#define ISO_a        0x61
#define ISO_t        0x74
#define ISO_hash     0x23
#define ISO_period   0x2e

struct Gdata 
{
    char gdata_get[2000];
    int gdata_len;
    int http_states;
#define http_close  0x00
#define http_open   0x01
#define http_waithead  0x02
#define rcv_file 0x03
    char* phead_end;
    int conlen;
    char boundary[100];
    int boundary_len;
    int file_len;
    char file_data[10*1024*1024];
    char *pdata_begin;
    int  file_data_len;
};

struct Gdata http_data_get;

u8 net_pack[2000];
int fd = 0;
unsigned char buf[BUFSIZE];
const char* service_ip = "192.168.30.3";
unsigned char service_mac[6] = {0x32, 0x0c, 0x36, 0x7c, 0x00, 0x72};
struct in_addr	net_ip;
u32 tcp_sqn;
u32 cli_sqn;
void send_tcp_packet();
void http_process(u8 *pdatahttp, int http_data_len);
void http_head_paser(void);
void rcv_end(void);

unsigned long simple_strtoul(const char *cp, char **endp,
				unsigned int base)
{
	unsigned long result = 0;
	unsigned long value;

	if (*cp == '0') {
		cp++;
		if ((*cp == 'x') && isxdigit(cp[1])) {
			base = 16;
			cp++;
		}

		if (!base)
			base = 8;
	}

	if (!base)
		base = 10;

	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
	    ? toupper(*cp) : *cp)-'A'+10) < base) {
		result = result*base + value;
		cp++;
	}

	if (endp)
		*endp = (char *)cp;

	return result;
}

struct in_addr string_to_ip(const char *s)
{
	struct in_addr addr;
	char *e;
	int i;

	addr.s_addr = 0;
	if (s == NULL)
		return addr;

	for (addr.s_addr = 0, i = 0; i < 4; ++i) {
		ulong val = s ? simple_strtoul(s, &e, 10) : 0;
		addr.s_addr <<= 8;
		addr.s_addr |= (val & 0xFF);
		if (s) {
			s = (*e) ? e+1 : e;
		}
	}

	addr.s_addr = htonl(addr.s_addr);
	return addr;
}

unsigned int tapdev_read(void)
{
  fd_set fdset;
  struct timeval tv;
  int ret;
  
  tv.tv_sec = 1;
  tv.tv_usec = 0;

  FD_ZERO(&fdset);
  FD_SET(fd, &fdset); 
  ret = select(fd + 1, &fdset, NULL, NULL, &tv);
  if(ret == 0) {   
    return 0;
  } 
  ret = read(fd,buf, BUFSIZE);  
  if(ret == -1) {
    perror("tap_dev: tapdev_read: read");
  }
  //printf("c------------>s\n");

  return ret;
}

static inline struct in_addr net_read_ip(void *from)
{
	struct in_addr ip;

	memcpy((void *)&ip, (void *)from, sizeof(ip));
	return ip;
}

void arp_receive(struct ethernet_hdr *et, struct ip_hdr *ip, int len)
{
   int ret;
       	struct arp_hdr *arp;
	struct in_addr reply_ip_addr;
	u8 *pkt;
	int eth_hdr_size;
    arp = (struct arp_hdr *)ip;
	if (len < ARP_HDR_SIZE) {
		printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
		return;
	}
    if (ntohs(arp->ar_hrd) != ARP_ETHER)
		return;
	if (ntohs(arp->ar_pro) != PROT_IP)
		return;
	if (arp->ar_hln != ARP_HLEN)
		return;
	if (arp->ar_pln != ARP_PLEN)
		return;
	if (net_read_ip(&arp->ar_tpa).s_addr != net_ip.s_addr)
		return;
    if (arp->ar_op != ARPOP_REQUEST)
	printf("this pack is not a requuest\n");
    pkt = (u8 *)et;
    //eth_hdr_size = net_update_ether(et, et->et_src, PROT_ARP);
    //pkt += eth_hdr_size;
    arp->ar_op = htons(ARPOP_REPLY);
    memcpy(&arp->ar_tha, &arp->ar_sha, ARP_HLEN);
    memcpy(&arp->ar_tpa, &arp->ar_spa, 4);
    memcpy(&arp->ar_sha, &service_mac[0], ARP_HLEN);
    memcpy(&arp->ar_spa, &net_ip, 4);

    //printf("this is a arp request for us!\n");
    unsigned char sbuf[500];
    int slen = 0;
    memcpy(&sbuf[slen], &et->et_src[0], 6);
    slen += 6;
    memcpy(&sbuf[slen], &service_mac[0], 6);
    slen += 6;
    memcpy(&sbuf[slen], &et->et_protlen, 2);
    slen += 2;
    memcpy(&sbuf[slen], arp, 28);
    slen += 28;

   /* for(ret = 0; ret < slen; ret++)
    {
	    printf("%02x ", sbuf[ret]);
    }
    printf("\n");
    */
    write(fd, &sbuf[0], slen);

}

u16 chksum(u16 sum, u8 *data, int len)
{
  u16 t;
  u8 *dataptr;
  u8 *last_byte;

  dataptr = data;
  last_byte = data + len - 1;
  
  while(dataptr < last_byte) {	/* At least two more bytes */
    t = (dataptr[0] << 8) + dataptr[1];
    sum += t;
    if(sum < t) {
      sum++;		/* carry */
    }
    dataptr += 2;
  }
  
  if(dataptr == last_byte) {
    t = (dataptr[0] << 8) + 0;
    sum += t;
    if(sum < t) {
      sum++;		/* carry */
    }
  }

  /* Return sum in host byte order. */
  return sum;
}
struct ip_tcp_hdr {
    //ip head
	u8		ip_hl_v;	/* header length and version	*/
	u8		ip_tos;		/* type of service		*/
	u16		ip_len;		/* total length			*/
	u16		ip_id;		/* identification		*/
	u16		ip_off;		/* fragment offset field	*/
	u8		ip_ttl;		/* time to live			*/
	u8		ip_p;		/* protocol			*/
#define PROTO_TCP   6
	u16		ip_sum;		/* checksum			*/
	struct in_addr	ip_src;		/* Source IP address		*/
	struct in_addr	ip_dst;		/* Destination IP address	*/
    //tcp head
	u16		tcp_src;	/* source port		*/
	u16		tcp_dst;	/* destination port		*/
	u32		tcp_sqn;	/* 		*/
	u32		tcp_ack;	/*			*/
    u8      tcp_ofs;
    u8      tcp_flg;
#define TCP_FIN 0x01
#define TCP_SYN 0x02
#define TCP_RST 0x04
#define TCP_PSH 0x08
#define TCP_ACK 0x10
#define TCP_URG 0x20
#define TCP_CTL 0x3f
    u16     tcp_wnd;
    u16     tcp_sum;
    u16     tcp_urg;
    u8      tcp_opt[0];
};

struct psd_hdr
{
    u32 srcip;
    u32 dstip;
    u8  mbz;
    u8  pro;
    u16 len;
};
// The TCP states. 
#define TCP_CLOSED      0
#define TCP_SYN_RCVD    1
#define TCP_SYN_SENT    2
#define TCP_ESTABLISHED 3
#define TCP_FIN_WAIT_1  4
#define TCP_FIN_WAIT_2  5
#define TCP_CLOSING     6
#define TCP_TIME_WAIT   7
#define TCP_LAST_ACK    8
#define TCP_TS_MASK     15
  
#define TCP_STOPPED   16

int tcp_states = TCP_CLOSED;
u16 ip_chksum(struct ip_hdr *ip)
{
    u8 ip_hdr_len = (ip->ip_hl_v & 0x0f)*4;
    return(chksum(0, (u8 *)ip, ip_hdr_len));
}

u16 tcp_chksum(struct ip_hdr *ip)
{
    struct psd_hdr psd;
    u8 ip_offset = (ip->ip_hl_v & 0x0f) * 4;
    memcpy(&psd.srcip, &ip->ip_src, 4);
    memcpy(&psd.dstip, &ip->ip_dst, 4);
    psd.mbz = 0;
    memcpy(&psd.pro, &ip->ip_p, 1);
    psd.len = htons(ntohs(ip->ip_len) - ip_offset);
    return(chksum(chksum(0, (unsigned char *)&psd,sizeof(psd)), ((unsigned char *)ip)+ip_offset, ntohs(psd.len)));


}
void tcp_receive(struct ethernet_hdr *et, struct ip_hdr *ip, int len)
{
    struct ip_tcp_hdr *tcp, *tcpsend;

    tcp = (struct ip_tcp_hdr *)ip;
    tcpsend = (struct ip_tcp_hdr *)(net_pack+14);
    //int lenhttp;
    int slen = 0;
    //int maclen;
    //int iplen;
    int tcphdr_len;
    u32 data_len;
    char *data1;

    if(tcp->ip_p != IPPROTO_TCP)
       	{
	       	printf("not a tcp pack \n");
                return;
        }
	if (net_read_ip(&tcp->ip_dst).s_addr != net_ip.s_addr)
	{
                printf("ip not forf us \n");
	       	return;
       	}	
    if(ip_chksum(ip) != 0xffff)
    {
        printf("bad ip checksum \n");
        return;
    }
    if(tcp_chksum(ip) != 0xffff)
    {
        printf("bad tcp checksum \n");
        return;
    }
    data_len = ntohs(tcp->ip_len) - ((tcp->ip_hl_v & 0x0f)*4) - (tcp->tcp_ofs >>2);
    printf("c-----s sqn %u, ack %u, len %u , iphead %u, tcphead %u, data_len %u\n", ntohl(tcp->tcp_sqn), ntohl(tcp->tcp_ack), ntohs(tcp->ip_len), (tcp->ip_hl_v & 0x0f)*4, tcp->tcp_ofs >>2,  data_len);
    switch(tcp_states)	
    {
    case TCP_CLOSED:
        //just deal TCP_SYN packet
	//sent back svr TCP_SYN packet
	//tcp_states change to TCP_SYN_RCVD
	if(tcp->tcp_flg ==  TCP_SYN)
        {

            printf("tcp_syn\n");
	    //ether head
            memcpy(net_pack, &et->et_src[0], 6);
            memcpy(net_pack+6, &et->et_dest[0], 6);
            memcpy(net_pack+12, &et->et_protlen, 2);
            //header length and version IPv4 ,20byte iphead 0x45
	    tcpsend->ip_hl_v = 0x45;
            //type of service 0x00
	    tcpsend->ip_tos = 0x00;
            //total length 40+httplen
            tcpsend->ip_len = htons(40);
            //identification htons(0x7296);
            tcpsend->ip_id = htons(0x7296); 
            //fragment offset field 0x4000
            tcpsend->ip_off = htons(0x4000);  
            //time to live 0x80
            tcpsend->ip_ttl = 0x80;   
            //protocol PROTO_TCP   0x06
	    tcpsend->ip_p = 0x06;    
            memcpy(&tcpsend->ip_src, &tcp->ip_dst, 4);
            memcpy(&tcpsend->ip_dst, &tcp->ip_src, 4);
            memcpy(&tcpsend->tcp_src, &tcp->tcp_dst, 2);
            memcpy(&tcpsend->tcp_dst, &tcp->tcp_src, 2);
            tcpsend->tcp_ack = htonl(ntohl(tcp->tcp_sqn) + 1);
            tcpsend->tcp_sqn = tcp->tcp_sqn * 9 / 5;
            tcpsend->tcp_ofs = 0x50;
	    tcpsend->tcp_flg = TCP_SYN|TCP_ACK;
            tcpsend->tcp_wnd = htons(0x900);
	    tcpsend->tcp_urg = 0x0000;
            send_tcp_packet();
            tcp_states =  TCP_SYN_RCVD;
	    tcpsend->tcp_sqn = htonl(ntohl(tcpsend->tcp_sqn) +1);
	    printf("tcp_states change to TCP_SYN_RCVD\n");
	}
	else if(data_len > 0)
	{
	    data1 = (char *)&tcp->tcp_opt;
	    for(slen = 0;slen < data_len; slen++)
	    {
	        printf("%c", *(data1+slen));
	    }
	    printf("\n");
	}

        break;
    case TCP_SYN_RCVD:
       	if((tcp->tcp_flg ==  TCP_ACK) && (tcp->tcp_sqn == tcpsend->tcp_ack) && (tcp->tcp_ack == tcpsend->tcp_sqn))
        {
            tcp_states = TCP_ESTABLISHED ;
            printf("tcp_states change to TCP_ESTABLISHED\n");
	}
	else
	{
	    printf("tcp->tcp_flg is %u, tcp->tcp_sqn %u, tcpsend->tcp_ack %u, tcp->tcp_ack) %u, tcpsend->tcp_sqn %u \n", tcp->tcp_flg, ntohl(tcp->tcp_sqn), ntohl(tcpsend->tcp_ack), ntohl(tcp->tcp_ack), ntohl( tcpsend->tcp_sqn));
	}
	break;
    case TCP_ESTABLISHED:
        //ack packet, fin packet, data packet
	//ack packet
	    if(tcpsend->tcp_sqn != tcp->tcp_ack)
	    {
	        printf("tcp->tcp_ack err\n");
	        break;
	    }
	if((tcp->tcp_flg ==  TCP_ACK) && (data_len == 0) &&( tcp->tcp_ack == tcpsend->tcp_sqn))
        {
	    printf("ack receive \n");
            break ;
        }
        //FIN packet
        else if(tcp->tcp_flg &  TCP_FIN)
        {
	    printf("fin receive \n");
	    tcpsend->tcp_ack = htonl(ntohl(tcp->tcp_sqn) + 1);
	    tcpsend->tcp_flg = TCP_ACK;
	    tcpsend->ip_len = htons(40);
            send_tcp_packet();
	    tcpsend->tcp_flg = TCP_ACK|TCP_FIN;
	    send_tcp_packet();
	    tcpsend->tcp_sqn = htonl(ntohl(tcpsend->tcp_sqn) + 1);
	    tcp_states = TCP_CLOSED;
	    printf("TCP_CLOSED \n");
    	}
	else if(data_len > 0 )
	{
	    //printf("tcp->ip_id:%x, tcp->ip_flag:%x, tcp->ip_off:%x \n", ntohs(tcp->ip_id), (tcp->ip_off&0xe000)>>13, ntohs(tcp->ip_off&0x1fff));
	    if(tcpsend->tcp_ack == tcp->tcp_sqn)
	    {
	        tcpsend->tcp_ack = htonl(ntohl(tcp->tcp_sqn) + data_len); 
            tcpsend->tcp_flg = TCP_ACK;
	        tcpsend->ip_len = htons(40);
	        send_tcp_packet();
            tcpsend->tcp_flg = TCP_ACK|TCP_PSH;
	        http_process((u8 *)&tcp->tcp_opt[0], data_len);
	    }
	    else
	    {
	        printf("sqn %d pack miss\n", ntohl(tcp->tcp_sqn));
	        tcpsend->tcp_flg = TCP_ACK;
	        tcpsend->ip_len = htons(40);
	        send_tcp_packet();
	        send_tcp_packet();
	        send_tcp_packet();
	    }
	    //web_not_found();
	}
	break;
    default:
	tcp_states = TCP_CLOSED;
	printf("can not deal this flg, tcp closed!\n");
	break;
    }
}

void send_tcp_packet()
{
    //u8    et_dest[6]; Destination node
    //u8    et_src[6];  Source node
    //u16   et_protlen; Protocol or length
    //u8    ip_hl_v;  header length and version IPv4 ,20byte iphead 0x45 
    //u8    ip_tos;   type of service 0x00
    //u16   ip_len;   total length 40+httplen
    //u16   ip_id;    identification 0x7296
    //u16   ip_off;   fragment offset field 0x4000
    //u8    ip_ttl;   time to live 0x80
    //u8    ip_p;     protocol PROTO_TCP   0x06
    //u16   ip_sum;   checksum
    //struct in_addr  ip_src;    Source IP address
    //struct in_addr  ip_dst;    Destination IP address
    //u16   tcp_src;  source port
    //u16   tcp_dst;  destination port
    //u32   tcp_sqn;  
    //u32   tcp_ack;
    //u8    tcp_ofs; 20byte 0x50 
    //u8    tcp_flg;
    //u16   tcp_wnd; 0x2000 
    //u16   tcp_sum;
    //u16   tcp_urg; 0x0000 
    // calculate ip_sum, tcp_sum and sent
    //
    //u8 *sbuf;
    int byte_send;
    int i;
    struct ip_tcp_hdr *tcpsend;
    tcpsend = (struct ip_tcp_hdr *)(net_pack+14);

    tcpsend->ip_sum = 0x0000;
    tcpsend->tcp_sum = 0x0000;
    tcpsend->ip_sum = htons(~ip_chksum((struct ip_hdr *)tcpsend));
    tcpsend->tcp_sum = htons(~tcp_chksum((struct ip_hdr *)tcpsend));
    byte_send = ntohs(tcpsend->ip_len) + 14;
    write(fd, net_pack, byte_send);//net_send_packet(net_pack, byte_send);
    printf("s-----c sqn %u, ack %u, len %u , iphead %u, tcphead %u\n", ntohl(tcpsend->tcp_sqn), ntohl(tcpsend->tcp_ack), ntohs(tcpsend->ip_len), (tcpsend->ip_hl_v & 0x0f)*4, tcpsend->tcp_ofs >>2);
   /*
    for(i=0; i<byte_send; i++)
    {
        printf("%02x ",net_pack[i]);
	if(i%16 == 15) printf("\n");
    }
    printf("\n");
    printf("byte_send is %d", byte_send);
    printf("\n");
    */
}

void http_process(u8 *pdatahttp, int http_data_len)
{
    u16 dlen = 0;
    u16 i;
    struct ip_tcp_hdr *tcpsend;
    tcpsend = (struct ip_tcp_hdr *)(net_pack+14);
    char *hdata = (char *)net_pack + 54;
    char *pget_http = (char *)pdatahttp;
    char *printfdata;
    
    char *start, *next, *end, *head_end;
    
    if(http_data_get.http_states == http_waithead)
	{
	    
	    memcpy(http_data_get.gdata_get+http_data_get.gdata_len, (char *)pdatahttp, http_data_len);
	    http_data_get.gdata_len += http_data_len;
	    http_data_get.gdata_get[http_data_get.gdata_len] = '\0';
	    http_data_get.phead_end = strstr(http_data_get.gdata_get, "\r\n\r\n");
	    if(http_data_get.phead_end)
	    {
	        printf("END of http POST head \n");
	        http_head_paser();
	    }
	    else
	    {
	        printf("MID of http POST head \n");
	        http_data_get.http_states = http_waithead;
	    }
	}
		
	else if(http_data_get.http_states == rcv_file)
	{
	    memcpy(http_data_get.file_data+http_data_get.file_len, (char *)pdatahttp, http_data_len);
	    http_data_get.file_len += http_data_len;
	    printf("rcv file data %d, http_data_len %d \n", http_data_get.file_len, http_data_get.conlen);
	    //if(http_data_get.file_len >= http_data_get.conlen/4)
	    //{
	    //    printf("rcv 1/4 file data \n");
	    //}
	    if(http_data_get.file_len >= http_data_get.conlen)
            {
                rcv_end();
                printf("rcv ALL file data \n");
                http_data_get.file_data[http_data_get.file_len]='\0';
                printfdata = http_data_get.file_data;
                //find "/r/n/r/n", set pdata_begin
                start = strstr(http_data_get.file_data, "\r\n\r\n");
                http_data_get.pdata_begin =  start + 4;
                start = http_data_get.file_data + http_data_get.file_len - 2;
                for(i = 0; i < 100; i++)
                {
                    if((*(start-i-1) == '\r') && (*(start-i) == '\n'))
                    {
                        http_data_get.file_data_len = start-i-1 - http_data_get.pdata_begin;
                        printf("file_data_len: %d \n", http_data_get.file_data_len);
                        break;
                    }
                }
                //for(i=0; i<http_data_len; i++)
                //    printf("%c", *((char *)pdatahttp+i));
                //printf("\n");
                        
            }
	    /*
	    *((char *)pdatahttp + http_data_len) = '\0';
	    start = strstr((char *)pdatahttp, http_data_get.boundary);
        if(start)
        {
            printf("pack WITH file data \n");
            //start = strstr((char *)pdatahttp, "\r\n\r\n");
            //start += 4;
            next = strstr((start+http_data_get.boundary_len), http_data_get.boundary);
            if(next)
            {
                next = strstr(next, "\r\n");
                next += 2;
                printf("end of file data FOUND \n");
                memcpy(http_data_get.file_data + http_data_get.file_len, start, next-start);
                http_data_get.file_len += next-start;
                if(http_data_get.file_len > http_data_get.conlen)
                {
                    rcv_end();
                    printf("rcv ALL file data \n");
                        
                }
            }
            else
            {
                printf("end of file data NOTFOUND \n");
            }
        }
        */
	    
	}
    else if(*pget_http == ISO_G &&
	   *(pget_http + 1) == ISO_E &&
	   *(pget_http + 2) == ISO_T &&
	   *(pget_http + 3) == ISO_space)
	{
	    printf("get\n");
	    if(*(pget_http + 4) == ISO_slash && *(pget_http + 5) == ISO_space)
		{
		    printf("index\n");
		    dlen = sizeof(data_index_html);
		    memcpy(hdata, data_index_html, dlen);
		}
		else
		{
		    printf("404\n");
		    dlen = sizeof(data_404_html);
		    memcpy(hdata, data_404_html, dlen);   
		}
		tcpsend->ip_len = htons(40 + dlen);
        send_tcp_packet();
        tcpsend->tcp_sqn = htonl(ntohl(tcpsend->tcp_sqn) + dlen);
        
        tcpsend->ip_len = htons(40);
        tcpsend->tcp_flg = TCP_ACK|TCP_FIN;
        send_tcp_packet();
        tcpsend->tcp_sqn = htonl(ntohl(tcpsend->tcp_sqn) + 1);
	}
	else if(*pget_http == ISO_P &&
	   *(pget_http + 1) == ISO_O &&
	   *(pget_http + 2) == ISO_S &&
	   *(pget_http + 3) == ISO_T &&
	   *(pget_http + 4) == ISO_space)
	{
	    memcpy(http_data_get.gdata_get, (char *)pdatahttp, http_data_len);
	    http_data_get.gdata_len = http_data_len;
	    http_data_get.gdata_get[http_data_get.gdata_len] = '\0';
	    http_data_get.phead_end = strstr(http_data_get.gdata_get, "\r\n\r\n");
	    if(http_data_get.phead_end)
	    {
	        printf("this head contain a WHOLE http POST head \n");
	        http_head_paser();
	    }
	    else
	    {
	        printf("this head contain a PART of http POST head \n");
	        http_data_get.http_states = http_waithead;
	    }
	    
	}

	
	else
	{
	    printf("?????????????\n");
	    tcpsend->ip_len = htons(40 + dlen);
        send_tcp_packet();
        tcpsend->tcp_sqn = htonl(ntohl(tcpsend->tcp_sqn) + dlen);
        
        tcpsend->ip_len = htons(40);
        tcpsend->tcp_flg = TCP_ACK|TCP_FIN;
        send_tcp_packet();
        tcpsend->tcp_sqn = htonl(ntohl(tcpsend->tcp_sqn) + 1);
	}
			
    
    
    
}

void http_head_paser(void)
{
    char *start, *next, *end;
    http_data_get.http_states = http_open;
	*(http_data_get.phead_end) = '\0';
	printf("%s", http_data_get.gdata_get);
    printf("\n");
    start = strstr(http_data_get.gdata_get, "Content-Length: ");
    if(start)
    {
        start += sizeof("Content-Length:");
        next = strstr(start, "\r\n");
        if(next)
        {
            http_data_get.conlen  = atoi(start);
            printf("Content-Length: %d\n", http_data_get.conlen);
        }
        else
        {
            printf("can not found Content-Length end\n");
        }
    }
    else
    {
         printf("can not found Content-Length \n");
    }
    
    start = strstr(http_data_get.gdata_get, "boundary=");
    if(start)
    {
        start += sizeof("boundary=");
        next = strstr(start, "\r\n");
        if(next)
        {
            http_data_get.boundary_len = next-start;
            memcpy(http_data_get.boundary, start, http_data_get.boundary_len);
            http_data_get.boundary[next-start] = '\0';
            http_data_get.http_states = rcv_file;
            printf("boundary=%s, boundary_len is %d \n", http_data_get.boundary, http_data_get.boundary_len);
            
            start = strstr(next, http_data_get.boundary);
            if(start)
            {
                start += http_data_get.boundary_len;
                printf("head WITH file data \n");
                next = strstr(start, http_data_get.boundary);
                if(next)
                {
                    printf("end of file data FOUND \n");
                    http_data_get.file_len = next-start;
                    memcpy(http_data_get.file_data, start, http_data_get.file_len);
                    if(http_data_get.file_len == http_data_get.conlen)
                    {
                        rcv_end();
                        printf("rcv ALL file data \n");
                        
                    }
                }
                else
                {
                    http_data_get.file_len = 0;
                    printf("end of file data NOTFOUND \n");
                }
            }
            else
            {
                http_data_get.file_len = 0;
                printf("head WHITOUT file data \n");
            }
        }
        else
        {
            printf("can not found boundary end \n");
        }
    }
    else
    {
         printf("can not found boundary \n");
    }
}

void rcv_end(void)
{
    u16 dlen;
    char *hdata = (char *)net_pack + 54;
    struct ip_tcp_hdr *tcpsend;

    tcpsend = (struct ip_tcp_hdr *)(net_pack+14);
    
    dlen = sizeof(data_receive_html);
    memcpy(hdata, data_receive_html, dlen);
    tcpsend->ip_len = htons(40 + dlen);
    send_tcp_packet();
    tcpsend->tcp_sqn = htonl(ntohl(tcpsend->tcp_sqn) + dlen);
        
    tcpsend->ip_len = htons(40);
    tcpsend->tcp_flg = TCP_ACK|TCP_FIN;
    send_tcp_packet();
    tcpsend->tcp_sqn = htonl(ntohl(tcpsend->tcp_sqn) + 1);
    
    http_data_get.http_states = http_close;
}

int main(void)
{

	int ret = 0;
    struct ethernet_hdr *et;
    struct ip_hdr *ip;
    int i;
    int writenum;
    int fd_record;
    int eth_proto;
    int len;
    char recordbuf[5000];
    char cmdbuf[500];
    net_ip = string_to_ip(service_ip);

    //printf("Hello world!\n");//这是一个测试
    fd = open("/dev/net/tun", O_RDWR);
    if(fd == -1) {
    perror("tapdev: tapdev_init: open");
    exit(1);
    }
    //printf("fd is %d \n", fd);

    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
    if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
      perror(cmdbuf);
      exit(1);
    }

    snprintf(cmdbuf, sizeof(cmdbuf), "ifconfig tap0 inet %d.%d.%d.%d", 192, 168, 30, 1);
    system(cmdbuf);
    //while(getchar() != 'q')
    while(1)
    {
        len = tapdev_read();
        if(len > 0)
        {
            //printf("%d data have been recieved \n", len);
	    for(i=0, ret=0, writenum=0; i<len; i++)
	    {
		    ret=sprintf(recordbuf+writenum, "%02x ",*(buf+i));
		    writenum += ret;
	    }
        /*
	    fd_record = open("./1.txt", O_RDWR);
            if(fd_record == -1) {
                perror("open record file fail");
            }
            lseek(fd_record, 0, SEEK_END);
            write(fd_record, recordbuf, writenum); 
            write(fd_record, "\n\n", 2); 
            close(fd_record);
            */
            if (len < ETHER_HDR_SIZE)
            {
                printf(" too small packet \n");
                return 0;
            }
            et = (struct ethernet_hdr *)buf;
            eth_proto = ntohs(et->et_protlen);
            /*
            printf("Protocol or length is %hu \n", eth_proto);
            printf("Dst MAC is:");
            for(i=0; i<5; i++)
            {
                printf("%x. ", et->et_dest[i]);                               
            }
            printf("%x\n", et->et_dest[i]);  

            printf("Src MAC is:");
            for(i=0; i<5; i++)
            {
                printf("%x. ", et->et_src[i]);                               
            }
            printf("%x\n", et->et_src[i]);
            */
            if (eth_proto < 1514) {
		        /*
		         *	Got a 802.2 packet.  Check the other protocol field.
	             *	XXX VLAN over 802.2+SNAP not implemented!
		         */
                 continue;

	        } else {	/* normal packet */
		       ip = (struct ip_hdr *)(buf + ETHER_HDR_SIZE);
		       len -= ETHER_HDR_SIZE;
		       switch(eth_proto){
			case PROT_ARP:
			       //printf("recieve an ARP pack.\n");
                   arp_receive(et, ip, len);
			       break;
			case PROT_IP:
			       //printf("recieve an IP pack.\n");
                   tcp_receive(et, ip, len);
			       break;
			default:
			       //printf("recieve an other pack.\n");
			       break;
		       }

	        }
	        /*
	        printf("DST MAC is\n");
	        for(i=0; i<6; i++)
	        {
	            printf("%02x ", *(buf+i));
	        }	
	        printf("\n");
	        
	        printf("SUR MAC is\n");
	        for(; i<12; i++)
	        {
	            printf("%02x ", *(buf+i));
	        } 
	        printf("\n");
	        
	        printf("PRO is\n");  
	        for(; i<14; i++)
	        {
	            printf("%02x ", *(buf+i));
	        }
	        printf("\n");
	        
	        printf("data is\n");
	        for(; i<ret; i++)
	        { 
	            printf("%02x ", *(buf+i));
	            if(((i-14)%32) == 31) printf("\n");
	        }   
	        printf("\n");  
            */  

        }
    }
    close(fd);
}
